package lol.clann.minecraft.springboot.plugin.bukkit.impl;

import lol.clann.minecraft.springboot.api.bukkit.utils.*;
import lol.clann.minecraft.springboot.api.model.reflect.MethodInvoker;
import lol.clann.minecraft.springboot.bukkit.plugin.AdapterContext;
import lol.clann.minecraft.springboot.bukkit.utils.CraftClasses;
import net.minecraft.server.v1_7_R4.BlockFluids;
import org.bukkit.block.Block;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 *
 * @author pyz
 * @date 2019/5/12 10:34 PM
 */
@Service
public class BlockUtilsImpl_all implements BlockUtils {

    private MethodInvoker getNMSBlock;
    private Class BlockFluidBase;
    @Autowired
    private WorldUtils worldUtils;
    @Autowired
    private InventoryUtils inventoryUtils;
    @Autowired
    private NBTUtils nbtUtils;
    @Autowired
    private LocationUtils locationUtils;
    @Autowired
    private TileEntityUtils tileEntityUtils;

    @PostConstruct
    private void init() throws NoSuchMethodException, ClassNotFoundException {
        getNMSBlock = new MethodInvoker(CraftClasses.getCraftBlock().getDeclaredMethod("getNMSBlock", new Class[0]));
        if (AdapterContext.isForge()) {
            BlockFluidBase = Class.forName("net.minecraftforge.fluids.BlockFluidBase");
        }
    }

    @Override
    public boolean isFliud(Block b) {
        if (isEmpty(b)) {
            return false;
        }
        if (b.isLiquid()) {
            return true;
        }
        Object nmsBlock = toNMS(b);
        if (nmsBlock == null) {
            return false;
        }
        if (nmsBlock instanceof BlockFluids || (AdapterContext.isForge() && BlockFluidBase.isInstance(nmsBlock))) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isInventory(Block block) {
        if (isEmpty(block)) {
            return false;
        }
        Object te = worldUtils.getTileEntity(block);

        if (te != null && inventoryUtils.isNMSInventory(te)) {
            return true;
        }
        return false;
    }

    @Override
    public Object toNBTTagCompound(Block block) {
        if (block == null) {
            return null;
        }
        Object tag = nbtUtils.newNBTTagCompound();
        nbtUtils.setValue(tag, "id", block.getType().name());
        nbtUtils.setValue(tag, "data", block.getData());
        nbtUtils.setValue(tag, "loc", locationUtils.toNBTTagCompound(block.getLocation()));
        Object te = worldUtils.getTileEntity(block);
        if (te != null) {
            nbtUtils.setValue(tag, "tileentity", tileEntityUtils.toNBTTagCompound(te));
        }
        return tag;
    }

    @Override
    public <T> T toNMS(Block block) {
        return (T) getNMSBlock.invoke(block);
    }
}
